#include <pronano.h>
#include <measurement.h>

volatile uint32_t adc_data_ready = 0, redundancy_entry = 0;
int cur_phase = 1, zero_count = 0, adc_temp = 0, iteration = 0;
volatile int adc_data[Measure_phases][Measure_times];
double mean[Max_Evaluate_Iteration], mean1[Max_Evaluate_Iteration];
int Is_blank = 0;

/*20130430 added by michael*/
void MaestroNano_Capture(int phase, int samples) {
/* pahse 0: blank_init_E or sample_init_E*/
/* pahse 1: blank_E or sample_E*/
  int i = 0;// cur_adc_data_ready = 0;

  //count1 = 0;
  zero_count = 0;
  redundancy_entry = 0;
  //printf("last time adc_data_ready: %d\n", adc_data_ready);
  adc_data_ready = 0;
  printf("start adc_data_ready: %d\n", adc_data_ready);
  DDC114_Start_Conversion();
  while (adc_data_ready < (samples+throw_samples)) {
#ifdef Measure_test_mode
  if (Is_blank) {
	  if (phase) {
        adc_data[cur_phase][adc_data_ready-throw_samples] = rand() % 1000 + 333333;
	    adc_data_ready++;
	  }
	  else {
         adc_data[cur_phase][adc_data_ready-throw_samples] = rand() % 500 + 3500;
         adc_data_ready++;
	  }
	//Delay100ms(1);
  }
  else {
	  if (phase) {
        adc_data[cur_phase][adc_data_ready-throw_samples] = rand() % 1000 + 300000;
	    adc_data_ready++;
	  }
	  else {
         adc_data[cur_phase][adc_data_ready-throw_samples] = rand() % 1000 + 3500;
	     adc_data_ready++;	  
	  }
	  //Delay100ms(1);
  }
#endif
    //printf("adc_data_ready: %d\n", adc_data_ready);
    //SysTimerDelay(1);
	//Delay100ms(1);
  }

  DDC114_Stop_Conversion();
  printf("measure complete\n");
  LED562_OFF
  LED595_OFF
  LED660_OFF
  //Xenon_Flash_Off();
  printf("stop adc_data_ready: %d\n", adc_data_ready);

  printf("zero count: %d, inteference count: %d\n", zero_count, redundancy_entry);
/*#ifdef MaestroNano_DEBUG
  for (i = 0; i < Measure_times; i++)
    printf("index: %d, Conversion result: 0x%X (%d)\n", i, adc_data[phase][i], adc_data[phase][i]);
#endif*/
}

/*20130430 added by michael*/
void ProNano_Measure() {
	int i, j, k, threshold, start_index;

	memset((adc_data), 0x0, sizeof(adc_data));;
	//capture intensity with Xenon_Flash_On
	for (i = 1; i >= 0; i--) {
       switch (i) {
		 case 0:
#ifdef ProNano_DEBUG
		   //printf("When blank is ready, then press any key\n");
		   //printf("measure phase 0: blank_init_E\n");
#endif
           cur_phase = 0;
           Led_Off();
		   switch (Assay_index) {
		     case 0:
			    LED562_OFF
                break;
			 case 1:
				LED595_OFF
                break;
			 case 2:
				LED660_OFF
                break;
		   }
		   //Delay100ms(1);
		   //may need some delay
		   //PWM_Init();
		   //DDC114_Start_Conversion();
		   MaestroNano_Capture(i, Measure_times);
		   break;

	     case 1:
#ifdef ProNano_DEBUG
		   //printf("measure phase 1: blank_E\n");
#endif
		   cur_phase = 1;
//		   Led_On();
           LED562_OFF
           LED595_OFF
           LED660_OFF
		   switch (Assay_index) {
		     case 0:
			    LED562_ON
				Led_On(3);
                break;
			 case 1:
				LED595_ON
				Led_On(2);
                break;
			 case 2:
				LED660_ON
				Led_On(1);
                break;
		   }
		   //SysTimerDelay(3);
		   //may need some delay
		   //PWM_Init();
		   //DDC114_Start_Conversion();
		   MaestroNano_Capture(i, Measure_times);
		   //MaestroNano_Capture(i, 100);
		   break;
		}
	}

/*20130502 added by michael*/
#ifdef ProNano_DEBUG
    mean[iteration] = mean1[iteration] = 0;
	for (k = 0; k < Measure_times; k++) {
		printf("%ld %ld\n", adc_data[0][k], adc_data[1][k]);
		//  A230, Ch0
		mean[iteration] += adc_data[0][k];
		mean1[iteration] += adc_data[1][k];
	}

	iteration++;
    for (k = 0; k < iteration; k++)  {
	   printf("%lf  %lf\n", mean[k]/(Measure_times), mean1[k]/(Measure_times));
    }

	if (iteration==Max_Evaluate_Iteration)
		iteration = 0;

#endif //ProNano_DEBUG
}

int Add_measurement(struct Measure_tran *pMea_tran, int type) //type: 0,blank; type: 1,BCA; type: 2,Bradford; type: 3,Pierce
{
	int i;
	double Iblank, Isample, ODXXX;

	pMea_tran->err_status = 0;
	if (type==0) {
		Is_blank = 1;
		if (pMea_tran->blank_flag==-1) {

			pMea_tran->blank_AXXX.Non_Xenon_I = pMea_tran->blank_AXXX.Xenon_I = 0.0;

			ProNano_Measure();
			DDC114_Start_Conversion();
			DDC114_Stop_Conversion();
			printf("PDCR: %d\n", DrvPWM_GetTimerCounter(DRVPWM_TIMER0));
/*20130502 added by michael*/
#ifdef ProNano_DEBUG
			if ((iteration-1) < 0) {
	          pMea_tran->blank_AXXX.Non_Xenon_I = mean[Max_Evaluate_Iteration-1] / Measure_times;
	          pMea_tran->blank_AXXX.Xenon_I = mean1[Max_Evaluate_Iteration-1] / Measure_times;
			}
			else {
	           pMea_tran->blank_AXXX.Non_Xenon_I = mean[iteration-1] / Measure_times;
	           pMea_tran->blank_AXXX.Xenon_I = mean1[iteration-1] / Measure_times;
			}
#else
			for (i = 0; i < Measure_times; i++) {
			   pMea_tran->blank_AXXX.Non_Xenon_I += adc_data[0][i];
			   pMea_tran->blank_AXXX.Xenon_I += adc_data[1][i];
			}
			pMea_tran->blank_AXXX.Non_Xenon_I /= Measure_times;
			pMea_tran->blank_AXXX.Xenon_I /= Measure_times;
#endif

			Iblank = pMea_tran->blank_AXXX.Xenon_I - pMea_tran->blank_AXXX.Non_Xenon_I;
			switch (Assay_index) {
			  case 0:
				  if (Iblank < I_Led_562 || Iblank < 0)
					  pMea_tran->err_status |= Led_562_fail;
				  break;
			  case 1:
				  if (Iblank < I_Led_595 || Iblank < 0)
					  pMea_tran->err_status |= Led_595_fail;
				  break;
			  case 2:
				  if (Iblank < I_Led_660 || Iblank < 0)
					  pMea_tran->err_status |= Led_660_fail;
				  break;
			}

			printf("blank error: %d, backgrounf: %lf, Xenon: %lf\n", pMea_tran->err_status, pMea_tran->blank_AXXX.Non_Xenon_I, pMea_tran->blank_AXXX.Xenon_I);
			if (pMea_tran->err_status) {
				/*UNLOCKREG();
				WDT->WTCR.WTE = 0; //Disable WDT
				LOCKREG();*/
				return -1;
			}

			pMea_tran->blank_flag = 1;
            if (!is_RTC_Low_Power())
              Get_Maestro_RTC(&pMea_tran->date[0], 5);
			return 0;
		}
		else {
			/*UNLOCKREG();
			WDT->WTCR.WTE = 0; //Disable WDT
			LOCKREG();*/
			return 1;
		}  //if (pMea_tran->blank_flag==-1)
	}
	else {
       Is_blank = 0;
	   pMea_tran->sample_index++;
	   pMea_tran->samples_AXXX.Xenon_I = pMea_tran->samples_AXXX.Non_Xenon_I = 0.0;
	   
	   ProNano_Measure();
/*20130503 added by michael*/
#ifdef ProNano_DEBUG
	   if ((iteration-1) < 0) {
		   pMea_tran->samples_AXXX.Non_Xenon_I = mean[Max_Evaluate_Iteration-1] / Measure_times;
		   pMea_tran->samples_AXXX.Xenon_I = mean1[Max_Evaluate_Iteration-1] / Measure_times;
	   }
	   else {
		   pMea_tran->samples_AXXX.Non_Xenon_I = mean[iteration-1] / Measure_times;
		   pMea_tran->samples_AXXX.Xenon_I = mean1[iteration-1] / Measure_times;
	   }
#else
	   for (i = 0; i < Measure_times; i++) {
		   pMea_tran->samples_AXXX.Non_Xenon_I += adc_data[0][i];
		   pMea_tran->samples_AXXX.Xenon_I += adc_data[1][i];
	   }
	   pMea_tran->samples_AXXX.Non_Xenon_I /= Measure_times;
	   pMea_tran->samples_AXXX.Xenon_I /= Measure_times;
#endif
	
	   if (!pMea_tran->samples_AXXX.Xenon_I) {
		   pMea_tran->sample_index--;
		   return -1;
	   }

	   Iblank = pMea_tran->blank_AXXX.Xenon_I - pMea_tran->blank_AXXX.Non_Xenon_I;
	   Isample = pMea_tran->samples_AXXX.Xenon_I - pMea_tran->samples_AXXX.Non_Xenon_I;

	   if (Iblank > Isample && Iblank > 0 && Isample > 0) {
		   ODXXX = log10(Iblank/Isample);
		   pMea_tran->AXXX[pMea_tran->sample_index] = ODXXX;
#ifdef APP_DEBUG
           switch (Assay_index) {
             case 0:
               printf("index: %d, OD562: %lf, %lf\n", pMea_tran->sample_index, ODXXX);
			   break;
			 case 1:
				 printf("index: %d, OD595: %lf\n", pMea_tran->sample_index, ODXXX);
				 break;
			 case 2:
				 printf("index: %d, OD660: %lf\n", pMea_tran->sample_index, ODXXX);
				 break;
		   } 
#endif
	   }
#ifdef MaestroNano_OD_Allow_Negative
	   else 
		   if (Iblank <= Isample && Iblank > 0 && Isample > 0) {
			   ODXXX = log10(Isample/Iblank);
			   pMea_tran->AXXX[pMea_tran->sample_index] = ODXXX;
#ifdef APP_DEBUG
			   switch (Assay_index) {
                 case 0:
                   printf("index: %d, OD562: %lf\n", pMea_tran->sample_index, ODXXX);
				   break;
				 case 1:
					 printf("index: %d, OD595: %lf\n", pMea_tran->sample_index, ODXXX);
					 break;
				 case 2:
					 printf("index: %d, OD660: %lf\n", pMea_tran->sample_index, ODXXX);
					 break;
			   } 
#endif
		   }
#endif
		   else 
		   {
#ifdef APP_DEBUG
			   printf("AXXX, blank: %lf, sample: %lf\n", Iblank, Isample);
			   printf("%lf  %lf  %lf  %lf\n", pMea_tran->blank_AXXX.Xenon_I, pMea_tran->blank_AXXX.Non_Xenon_I, pMea_tran->samples_AXXX.Xenon_I, pMea_tran->samples_AXXX.Non_Xenon_I);
#endif
			   pMea_tran->sample_index--;
			   switch (Assay_index) {
				 case 0:
					 return -2;
					 break;
				 case 1:
					 return -3;
					 break;
				 case 2:
					 return -4;
					 break;
			   }
		   }
		   pMea_tran->sample_No[pMea_tran->sample_index] = ++pMea_tran->last_sample_No;
/*20130506 added by michael
bug fixed*/
		   memset(&pMea_tran->date[pMea_tran->sample_index+1], 0, sizeof(union MaestroDate ));
		   if (!is_RTC_Low_Power())
			   Get_Maestro_RTC(&pMea_tran->date[pMea_tran->sample_index], 5);
		   return 0;
	}
}


//==============================================================================
//Subroutine:	del_measurement
//Function: Do a measure iteration
//==============================================================================
int Del_measurement(struct Measure_tran *pMea_tran, int sample_index)
{
  int i, tail = 1;
  if (pMea_tran->sample_index >= 0) {
	for (i = sample_index; i < pMea_tran->sample_index; i++) {
	   pMea_tran->sample_No[i] = pMea_tran->sample_No[i+1];
	   pMea_tran->AXXX[i] = pMea_tran->AXXX[i+1];
	   tail = 0;
	}
	pMea_tran->sample_index--;
  }
  return tail;
}